package com.woniu.service.impl;

import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.io.FileUtil;
import cn.hutool.json.JSONUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.woniu.client.*;
import com.woniu.client.dto.*;
import com.woniu.exception.RebornException;
import com.woniu.mapper.StationMapper;
import com.woniu.mapper.StationRefuseJunkMapper;
import com.woniu.model.Coordinate;
import com.woniu.model.Result;
import com.woniu.model.Station;
import com.woniu.model.StationRefuseJunk;
import com.woniu.service.StationService;
import com.woniu.service.param.*;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.woniu.comment.util.LocationUtils;
import com.woniu.comment.util.OSSUtil;
import io.seata.spring.annotation.GlobalTransactional;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestParam;

import javax.annotation.Resource;
import java.math.BigDecimal;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * <p>
 * 服务实现类
 * </p>
 *
 * @author 吴彦祖
 * @since 2024年05月23日
 */
@Service
@Transactional
public class StationServiceImpl extends ServiceImpl<StationMapper, Station> implements StationService {

    @Resource
    private StationMapper stationMapper;
    @Resource
    private DepotClient depotClient;
    @Resource
    private JunkTypeClient junkTypeClient;
    @Resource
    private StationRefuseJunkMapper stationRefuseJunkMapper;

    @Resource
    private PermissionsClient permissionsClient;
    @Resource
    private EmployClient employClient;

    @Resource
    private OrderClient orderClient;

    /**
     * 添加站点
     *
     * @param param 添加站点参数
     * @throws RuntimeException 如果5公里内有其他站点，或者管理人不存在
     */
    @Override
    @GlobalTransactional(rollbackFor = Exception.class)//AT模式开启全局事务
    public void add(AddStationParam param) {
        Long curatorId = param.getCuratorId();//负责人id
        Result<EmployDto> result = employClient.findEmployeeByAccountId(String.valueOf(curatorId));
        if (result.getCode()!=200){
            throw new RebornException(result.getMessage(),result.getCode());
        }
        System.out.println("param: "+param.toString());

        EmployDto employ = result.getData();
        Station station = BeanUtil.toBean(param, Station.class);
        System.out.println("station: "+station.toString());
        station.setCuratorName(employ.getEmployeName());
        station.setCuratorPhone(employ.getPhone());


        // 转换时间格式
        DateTimeFormatter inputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd'T'HH:mm:ss.SSS");
        DateTimeFormatter outputFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime startTime = LocalDateTime.parse(param.getStartTime(), inputFormatter);
        LocalDateTime endTime = LocalDateTime.parse(param.getEndTime(), inputFormatter);
        station.setStartTime(startTime.format(outputFormatter));
        station.setEndTime(endTime.format(outputFormatter));


        station.setState(0);//记得改成常量
        station.setCuratorId(Math.toIntExact(employ.getAccountId()));
        //1.附近5公里内不能有其他站点
        //查出所有站点信息
        List<Station> stations = stationMapper.selectList(new QueryWrapper<Station>());
        //将所有站点信息的经纬度提取出来变成位置对象集合
        ArrayList<Coordinate> coordinates = new ArrayList<>();
        for (Station station1 : stations) {
            Coordinate coordinate = new Coordinate(Double.parseDouble(station1.getLongitude()), Double.parseDouble(station1.getLatitude()));
            coordinates.add(coordinate);
        }
        //调用工具类方法判断5公里内是否有其他站点
        boolean flag = LocationUtils.hasAnotherStation(Double.parseDouble(station.getLongitude()), Double.parseDouble(station.getLatitude()), coordinates, 10000);
        if (flag) {
            throw new RebornException("10公里内有其他站点,无法创建",90001);
        }
        stationMapper.insert(station);
        //新增站点之后,再更新权限模块中员工的"station_id"字段
        Result<EmployeeDto> employeeDtoResult = employClient.bindingStation(Math.toIntExact(param.getCuratorId()), station.getId());
        if (employeeDtoResult.getCode()!=200){
            throw new RebornException(employeeDtoResult.getMessage(),employeeDtoResult.getCode());
        }


    }

    /**
     * 删除站点
     *
     * @param id 站点ID
     * @throws RuntimeException 如果站点不存在，或者站点有资产未处理，或者有未开除的员工
     */
    @Override
    public void del(Integer id) {
        Station station = stationMapper.selectById(id);
        if (station == null) {
            throw new RuntimeException("不存在的站点id");
        }
        if (station.getState()!=1){
            throw new RebornException("站点状态非关闭,删除失败",60001);
        }
        //判断该站点是否有资产未处理干净
        Result<List<DepotDetialDto>> result = depotClient.findByStationId(id);
        if (result.getCode() != 200) {
            throw new RebornException(result.getMessage(),result.getCode());
        }
        List<DepotDetialDto> depotDetial = result.getData();

        if (depotDetial!=null && !depotDetial.isEmpty()) {
            for (DepotDetialDto detial : depotDetial) {
                //如果某一个废品小类的重量不等于0,则抛异常
                if (detial.getNumber().compareTo(BigDecimal.ZERO) != 0) {
                    Result<JunkTypeDto> result1 = junkTypeClient.getById(detial.getType());
                    if (result1.getCode() != 200) {
                        throw new RuntimeException(result1.getMessage());
                    }
                    JunkTypeDto junkType = result1.getData();
                    throw new RuntimeException("请检查," + junkType.getTypeName() + "还有" + detial.getNumber() + "库存未处理");
                }
            }
        }
        //判断是否存在没有开除的员工
        Integer curatorId = station.getCuratorId();//负责人id
        Result<Boolean> haveEmploye = employClient.isHaveEmploye(String.valueOf(station.getId()), String.valueOf(curatorId));
        if(haveEmploye.getCode()!=200){
            throw new RebornException(haveEmploye.getMessage(),haveEmploye.getCode());
        }
        if (haveEmploye.getData()) {
            throw new RebornException("该站点存在未开除的员工!请先安置好员工后删除站点",50001);
        }
        station.setState(2);
        stationMapper.updateById(station);
    }

    /**
     * 修改站点信息（包括图片）
     *
     * @param param 修改站点参数
     * @throws RuntimeException 如果站点不存在，或者站点已被删除
     */
    @Override
    public void modify(ModifyStationParam param) {
        boolean flag = false;//判断是否报错
        try {
            UpdateWrapper<Station> updateWrapper = new UpdateWrapper<>();
            Station station = stationMapper.selectById(param.getId());
            if (station == null) {
                throw new RuntimeException("不存在的站点");
            }
            if (station.getState().equals(1)) {
                throw new RuntimeException("该站点已被删除,无法操作");
            }
            //如果更新了图片 则把以前的图片删除掉(更新 不删 因为删了如果报错无法恢复  在finally里面处理 如果没报错 再删)
            if (param.isUpNew()) {
                //更新数据库图片地址
                station.setCard(param.getCard());
            }
            stationMapper.updateById(station);
        } catch (Exception e) {
            flag = true;
            if (param.isUpNew()) {
                //一旦报错，且更新了图片 就把新增上去的图片删掉
                OSSUtil.deleteFile("jinaisen", FileUtil.getName(param.getCard()));
            }
            throw e;//让AOP还是能拿到异常，做回滚
        } finally {
            //如果正常执行了程序 没有报错 再把以前的图片删掉
            if (!flag) {
                OSSUtil.deleteFile("jinaisen", param.getOldImg());
            }
        }
    }

    /**
     * 修改站点信息（不包括图片）
     *
     * @param param 修改站点参数
     * @throws RuntimeException 如果站点不存在，或者站点已被删除
     */
    @Override
    public void modify2(ModifyStation2Param param) {
        Station station = stationMapper.selectById(param.getId());
        if (station == null) {
            throw new RuntimeException("不存在的站点");
        }
        if (station.getState().equals(1)) {
            throw new RuntimeException("该站点已被删除,无法操作");
        }
        station.setName(param.getName()).setLongitude(param.getLongitude()).setLatitude(param.getLatitude()).setStartTime(param.getStartTime().toString()).setEndTime(param.getEndTime().toString()).setIntroduce(param.getIntroduce()).setState(param.getState()).setCuratorId(param.getCuratorId()).setCuratorName(param.getCuratorName()).setCuratorPhone(param.getCuratorPhone());
        stationMapper.updateById(station);
    }

    /**
     * 根据经纬度查找最近的站点
     *
     * @param param 查找最近站点参数
     * @return 最近的站点
     * @throws RuntimeException 如果附近五公里没有站点
     */
    @Override
    public Station findByLocation(FindByLocationParam param) {
        //通过一个经纬度 找到最近的站点
        //用户经纬度
        double longitude = param.getLongitude();
        double latitude = param.getLatitude();

        //找到所有站点的集合
        List<Station> stations = stationMapper.selectList(new QueryWrapper<Station>());
        //将站点变成经纬度坐标集合
        ArrayList<Coordinate> coordinates = new ArrayList<>();
        for (Station station : stations) {
            String longitude1 = station.getLongitude();//单个站点的经度
            String latitude1 = station.getLatitude();//单个站点的纬度
            Coordinate coordinate = new Coordinate(Double.parseDouble(longitude1), Double.parseDouble(latitude1));
            coordinates.add(coordinate);
        }
        Coordinate nearestCoordinate = LocationUtils.findNearestCoordinate(longitude, latitude, coordinates);
        if (nearestCoordinate != null) {
            //匹配最近的一个站点 经纬度与nearestCoordinate对象的经纬度相同
            for (Station station : stations) {
                if (Double.parseDouble(station.getLatitude()) == nearestCoordinate.getLatitude() && Double.parseDouble(station.getLongitude()) == nearestCoordinate.getLongitude()) {
                    return station;
                }
            }
        } else {
            throw new RuntimeException("附近五公里没有最近站点");
        }
        return null;
    }


    /**
     * 根据经纬度和垃圾种类查找最近的站点
     *
     * @param param 查找最近站点和垃圾种类参数
     * @return 最近的站点
     * @throws RuntimeException 如果附近五公里没有站点
     */
    @Override
    public Station findByLocationAndJunk(FindByLocationAndJunkParam param) {
        Set<Integer> ids = param.getIds();
        // 用户经纬度
        double longitude = param.getLongitude();
        double latitude = param.getLatitude();
        String time = param.getTime(); // 用户预约时间
        String newTime = time.substring(10);
        System.out.println(newTime);

//        LocalDateTime newNewTime = LocalDateTime.parse(newTime);
        System.out.println("传过来的经度： " + longitude);
        System.out.println("传过来的维度： " + latitude);
        // 找到所有站点的集合
        List<Station> stations = stationMapper.selectList(new QueryWrapper<Station>());
        // 将站点变成经纬度坐标集合
        List<Coordinate> coordinates = new ArrayList<>();

        // 使用迭代器遍历站点集合
        Iterator<Station> iterator = stations.iterator();
        while (iterator.hasNext()) {
            Station station = iterator.next();
            // 判断用户预约时间是否在站点营业时间内
            String startTime = station.getStartTime();// 站点开门时间
            String endTime = station.getEndTime();// 站点关门时间

            SimpleDateFormat simpleDateFormat = new SimpleDateFormat("HH:mm:ss");
            Date date;
            Date date1;
            Date date2;
            try {
                date = simpleDateFormat.parse(startTime);
                date1 = simpleDateFormat.parse(endTime);
                date2 = simpleDateFormat.parse(newTime);
            } catch (ParseException e) {
                throw new RuntimeException(e);
            }
            long time1 = date.getTime();// 站点开门时间
            long time2 = date1.getTime();// 站点关门时间
            long time3 = date2.getTime();// 用户预约时间
            System.out.println("用户下单时间：" +time3);
            System.out.println("关门时间：" +time2);
            System.out.println("开门时间：" +time1);
            // 比较用户预约时间是否在站点营业时间范围内
            if (time1> time3 || time3 >time2) {
                iterator.remove();
                System.out.println("移除站点（时间不符合）： " + JSONUtil.toJsonStr(station));
                continue;
            }

            // 筛选站点支持的垃圾种类
            QueryWrapper<StationRefuseJunk> wrapper = new QueryWrapper<StationRefuseJunk>().eq("station_id", station.getId());
            List<StationRefuseJunk> stationRefuseJunks = stationRefuseJunkMapper.selectList(wrapper);

            boolean isRefused = false;
            if (stationRefuseJunks != null && !stationRefuseJunks.isEmpty()) {
                for (StationRefuseJunk refuseJunk : stationRefuseJunks) {
                    if (ids.contains(refuseJunk.getRefuseJunkId())) {
                        isRefused = true;
                        break;
                    }
                }
            }

            if (isRefused) {
                iterator.remove();
                System.out.println("移除站点（垃圾种类不符合）： " + JSONUtil.toJsonStr(station));
                continue;
            }

            // 经过筛选后的站点，都是支持用户所选垃圾种类的站点
            String longitudeStr = station.getLongitude();
            String latitudeStr = station.getLatitude();
            Coordinate coordinate = new Coordinate(Double.parseDouble(longitudeStr), Double.parseDouble(latitudeStr));
            coordinates.add(coordinate);
        }

        System.out.println("筛选后的站点集合： " + JSONUtil.toJsonStr(stations));
        System.out.println("筛选后的坐标集合：" + JSONUtil.toJsonStr(coordinates));
        // 查找最近站点
        Coordinate nearestCoordinate = LocationUtils.findNearestCoordinate(longitude, latitude, coordinates);
//        // 计算用户与最近站点的直线距离 若大于30公里 则抛出异常
//        if (nearestCoordinate != null) {
//            // 计算用户位置与最近坐标的距离
//            double distance = LocationUtils.calcDistance(longitude, latitude, nearestCoordinate.getLongitude(), nearestCoordinate.getLatitude());
//            if (distance > 30000) {
//                throw new RebornException("抱歉,您所在的位置距离最近的站点"+distance/1000+"公里，暂不提供服务", 80002);
//            }
//        }
        if (nearestCoordinate != null) {
            // 匹配最近的一个站点，经纬度与nearestCoordinate对象的经纬度相同
            for (Station station : stations) {
                if (Double.parseDouble(station.getLatitude()) == nearestCoordinate.getLatitude() &&
                        Double.parseDouble(station.getLongitude()) == nearestCoordinate.getLongitude()) {
                    return station;
                }
            }
        } else {
            throw new RebornException("抱歉,您所在的位置暂不提供服务",80001);
        }
        return null;
    }

    /**
     * @param pageNum  分页pageNum
     * @param pageSize 分页pageSize
     * @return
     */
    @Override
    public Page<Station> loadAll(Integer pageNum, Integer pageSize) {
//        System.out.println("传过来的pageNum: "+pageNum);
//        System.out.println("传过来的pageSize: "+pageSize);
        pageNum = pageNum == null ? 1 : pageNum;
        pageSize = pageSize == null ? 3 : pageSize;
        Page<Station> page = new Page<>(pageNum, pageSize);
        Page<Station> stationPage = stationMapper.selectPage(page, new QueryWrapper<Station>());
        System.out.println(stationPage.getRecords());
//        System.out.println("page对象的total: "+page.getTotal());
//        System.out.println("total: "+stationPage.getTotal());
        return stationPage;
    }

    /**
     * 更改站点负责人
     * id 新负责人id
     */
    @Override
    public void changeHandler(Integer newHandlerId,Integer stationId) throws Exception {
        Result<AccountDto> result = permissionsClient.findAccountByAccountId(String.valueOf(newHandlerId));
        if (result.getCode()!=200){
            throw new RebornException(result.getMessage(),result.getCode());
        }
        AccountDto account = result.getData();
        if (account==null){
            throw new RebornException("不存在的账号id",10001);
        }
        Station station = stationMapper.selectById(stationId);
        if (station==null){
            throw new RebornException("不存在的站点",60001);
        }
        Result<EmployDto> result1 = employClient.findEmployeeByAccountId(String.valueOf(newHandlerId));
        if (result1.getCode()!=200) {
            throw new Exception("调用服务异常");
        }
        if (result1.getData()==null) {
            throw new Exception("查询的数据为空");
        }
        EmployDto data = result1.getData();
        station.setCuratorId(newHandlerId);
        station.setCuratorName(data.getEmployeName());
        station.setCuratorPhone(data.getPhone());
        updateById(station);
    }

    @Override
    public void changeState(Integer id) {
        Station station = stationMapper.selectById(id);
        if (station == null) {
            throw new RebornException("不存在的站点id",60001);
        }
        Integer state = station.getState();
        if (state==2){
            throw new RebornException("站点已被删除,无法操作",60002);
        }
       Integer newState = state==0 ? 1 : 0;
        station.setState(newState);
        stationMapper.updateById(station);
    }

    /**
     * 根据站点id查询站长账号id
     * id 站点id
     */
    @Override
    public Integer findBossByStationId(Integer id) {
        Station station = stationMapper.selectById(id);
        if (station==null){
            throw new RebornException("不存在的站点id",50001);
        }
        return station.getCuratorId();
    }

    @Override
    public Page<OrderDto> findUnHandelOrderByStationId(Integer id) {
//        orderClient.findById()
        return null;
    }

    @Override
    public Page<OrderDto> findOrderByStationId(Integer id,Integer pageNum,Integer pageSize) {
        Result<Page<OrderDto>> page =  orderClient.findByStationId(id,pageNum,pageSize);
        if (page.getCode()!=200){
            throw new RebornException(page.getMessage(),page.getCode());
        }
        return page.getData();
    }


}
